using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Xml.Linq;
using Dimebrain.TweetSharp.Extensions;
using Dimebrain.TweetSharp.Fluent;
using Dimebrain.TweetSharp.Model;
using twimilar.DomainModel;

namespace twimilar.Services
{
	internal class AccountService : IAccountService
	{
		private List<KeyValuePair<User, int>> _relevantUsers;
		private readonly IUsersRepositry _usersRepository;
		private readonly string _accountName;

		public AccountService(string name)
		{
			_accountName = name;
			_usersRepository = new UsersRepository();
		}

		#region IAccountService Members

		public Account Account { get; private set; }

		public List<KeyValuePair<User, int>> RelevantUsers
		{
			get
			{
				if (_relevantUsers == null)
				{
					_relevantUsers = GetRelevantUsers();
				}
				return _relevantUsers;
			}
		}

		#endregion

		private List<KeyValuePair<User, int>> GetRelevantUsers()
		{
			SetAccount();
			SetAccountWords(Account);
			SetAccountFriends();
			SearchForWords();
			return _usersRepository.TopUsersMoreThan1(Account);
		}

		public void SynchFriends(Account account, List<TwitterUser> users)
		{
			foreach (var twitterUser in users)
			{
				var user = new User(twitterUser);
				if (!account.Friends.Contains(user))
				{
					SetAccountWords(user);
					account.AddFriend(user);
				}
			}
		}

		private void SetAccount()
		{
			Account = new Account(FluentTwitter.CreateRequest()
															.Users().ShowProfileFor(_accountName).AsJson()
															.Request().AsUser());
		}

		private void SearchForWords()
		{
			Account.Words.GetTop(50).ForEach(SearchFor);
		}

		private void SetAccountFriends()
		{
			var ceiling = Math.Ceiling(Account.TwitterUser.FollowersCount / 100m);
			var results = new List<TwitterUser>();
			for (var i = 1; i <= ceiling; i++)
			{
				var fileName = string.Format("SetAccountFriends_{0}.txt", i);
				Debug.Print(fileName);
				string feed;
				if (File.Exists(fileName))
				{
					feed = File.ReadAllText(fileName);
				}
				else
				{
					feed = FluentTwitter.CreateRequest().
						Users().GetFriends().For(_accountName)
						.Skip(i).AsJson().Request();
					using (var stream = new StreamWriter(fileName))
					{
						stream.Write(feed);
					}
				}
				var users = feed.ToString().AsUsers();

				results.AddRange(users);
			}
			SynchFriends(Account, results);
		}

		private void SearchFor(string word)
		{
			var fileName = string.Format("SearchFor_{0}.txt", word).ToFileName();
			Debug.Print(fileName);
			XDocument feed;

			if (File.Exists(fileName))
			{
				feed = XDocument.Load(fileName);
			}
			else
			{
				string messages = FluentTwitter.CreateRequest().Search().Query().Containing(word).AsAtom().Request();
				feed = XDocument.Parse(messages);
				feed.Save(fileName);
			}
			_usersRepository.SynchUsers(feed.Root.Elements().Where(x => x.Name.LocalName == "entry").ToList());
		}

		public void SetAccountWords(User user)
		{
			string fileName = string.Format("SetAccountWords_{0}.txt", user.TwitterUser.ScreenName);
			Debug.Print(fileName);
			XDocument feed;

			if (File.Exists(fileName))
			{
				feed = XDocument.Load(fileName);
			}
			else
			{
				string messages = FluentTwitter.CreateRequest().Search().Query().FromUser(user.TwitterUser.ScreenName).AsAtom().Request();
				feed = XDocument.Parse(messages);
				feed.Save(fileName);
			}
			var entries = from x in feed.Root.Elements()
										where x.Name.LocalName == "entry"
										select x.Elements()
											.Where(element => element.Name.LocalName == "title")
											.First()
											.Value;
			entries.ToList().ForEach(user.AddTweet);
		}
	}
}